home *** CD-ROM | disk | FTP | other *** search
- #include "DemoRoutines.h"
- #include "math.h"
- #include "xform bitmap.h"
-
- #define use_box_filter 1
-
- void Assert(int assertion)
- {
- if (!assertion)
- Debugger();
- }
-
- shortFrac ShortFracMul(shortFrac a, shortFrac b)
- {
- return (long)a * b + halfShortFrac >> 14;
- }
-
- unsigned char ShortFracMulByte(shortFrac percent, unsigned char value)
- {
- return ShortFracMul(percent, value);
- }
-
- Boolean ModelessPtInRect(Point p, Rect* r)
- {
- return p.h < r->right && p.h >= r->left && p.v < r->bottom && p.v >= r->top;
- }
-
- /* This uses a 2x2 box filter with the coord at the upper left
- *
- * 1 1
- * 1 1
- */
-
- /* !!!! Note: it is illegal to call trap calls in this routine (that's why we use the ModelessPtInRect routine below). The
- caller needs to swap modes to 32 bit before calling this routine, and making trap calls in that state could crash the
- computer !!!! */
-
- Boolean GetFractionalPixel(long* srcBaseAddr, long srcRowLongs, Rect* srcBounds, Fixed fx, Fixed fy, long* dstLong )
- {
- unsigned long tempBlue, tempGreen, tempRed;
- long srcPixel[2][2];
- shortFrac scale[2][2];
- Point p;
-
- SetPt(&p, fx >> 16, fy >> 16);
- if (!ModelessPtInRect(p, srcBounds))
- return false;
-
- if (p.h == srcBounds->right - 1)
- fx = ff(p.h);
- if (p.v == srcBounds->bottom - 1)
- fy = ff(p.v);
-
- /* Compute the addr of the first src pixel
- */
- {
- long* srcAddr = srcBaseAddr + p.v * srcRowLongs + p.h;
-
- #if use_box_filter
- *dstLong = *srcAddr;
- return true;
- #endif
- srcPixel[0][0] = *srcAddr++;
- srcPixel[0][1] = *srcAddr++;
- srcAddr += srcRowLongs;
- srcPixel[1][1] = *--srcAddr;
- srcPixel[1][0] = *--srcAddr;
- }
-
- /* Precompute the scales for each pixel
- */
- { shortFrac xFrac = Fixed2ShortFrac((unsigned short)fx);
- shortFrac yFrac = Fixed2ShortFrac((unsigned short)fy);
-
- scale[0][0] = ShortFracMul(oneShortFrac - xFrac, oneShortFrac - yFrac);
- scale[0][1] = ShortFracMul(xFrac, oneShortFrac - yFrac);
- scale[1][0] = ShortFracMul(oneShortFrac - xFrac, yFrac);
- scale[1][1] = ShortFracMul(xFrac, yFrac);
- }
-
- /*
- * Now scale each component of each corner by the percentage coverage by the filter
- */
- tempBlue = ShortFracMulByte(scale[0][0], srcPixel[0][0]) +
- ShortFracMulByte(scale[0][1], srcPixel[0][1]) +
- ShortFracMulByte(scale[1][0], srcPixel[1][0]) +
- ShortFracMulByte(scale[1][1], srcPixel[1][1]);
- if (tempBlue == 256) tempBlue = 255;
- Assert(tempBlue >= 0 && tempBlue < 256);
-
- tempGreen = ShortFracMulByte(scale[0][0], srcPixel[0][0] >> 8) +
- ShortFracMulByte(scale[0][1], srcPixel[0][1] >> 8) +
- ShortFracMulByte(scale[1][0], srcPixel[1][0] >> 8) +
- ShortFracMulByte(scale[1][1], srcPixel[1][1] >> 8);
- if (tempGreen == 256) tempGreen = 255;
- Assert(tempGreen >= 0 && tempGreen < 256);
-
- tempRed = ShortFracMulByte(scale[0][0], srcPixel[0][0] >> 16) +
- ShortFracMulByte(scale[0][1], srcPixel[0][1] >> 16) +
- ShortFracMulByte(scale[1][0], srcPixel[1][0] >> 16) +
- ShortFracMulByte(scale[1][1], srcPixel[1][1] >> 16);
- if (tempRed == 256) tempRed = 255;
- Assert(tempRed >= 0 && tempRed < 256);
-
- *dstLong = (tempRed << 16) | (tempGreen << 8) | tempBlue;
- return true;
- }
-
-
- /* This uses a 2x2 box filter with the coord at the upper left
- *
- * 1 1
- * 1 1
- */
-
- /* !!!! Note: it is illegal to call trap calls in this routine (that's why we use the ModelessPtInRect routine below). The
- caller needs to swap modes to 32 bit before calling this routine, and making trap calls in that state could crash the
- computer !!!! */
-
- /* Editor's Note: I modified this routine to always use the box filter, for demo purposes. There's a similar routine
- below that uses only the tent filter, and above is the more general routine that's in the article */
- Boolean GetFractionalPixelBox(long* srcBaseAddr, long srcRowLongs, Rect* srcBounds, Fixed fx, Fixed fy, long* dstLong )
- {
- unsigned long tempBlue, tempGreen, tempRed;
- long srcPixel[2][2];
- shortFrac scale[2][2];
- Point p;
-
- SetPt(&p, fx >> 16, fy >> 16);
- if (!ModelessPtInRect(p, srcBounds))
- return false;
-
- if (p.h == srcBounds->right - 1)
- fx = ff(p.h);
- if (p.v == srcBounds->bottom - 1)
- fy = ff(p.v);
-
- /* Compute the addr of the first src pixel
- */
- {
- long* srcAddr = srcBaseAddr + p.v * srcRowLongs + p.h;
-
- *dstLong = *srcAddr;
- return true;
- }
- }
-
- /* This uses a 2x2 box filter with the coord at the upper left
- *
- * 1 1
- * 1 1
- */
-
- /* !!!! Note: it is illegal to call trap calls in this routine (that's why we use the ModelessPtInRect routine below). The
- caller needs to swap modes to 32 bit before calling this routine, and making trap calls in that state could crash the
- computer !!!! */
-
- /* Editor's Note: I modified this routine to always use the tent filter, for demo purposes. There's a similar routine
- above that uses only the box filter, and above that is the more general routine that's in the article */
- Boolean GetFractionalPixelTent(long* srcBaseAddr, long srcRowLongs, Rect* srcBounds, Fixed fx, Fixed fy, long* dstLong )
- {
- unsigned long tempBlue, tempGreen, tempRed;
- long srcPixel[2][2];
- shortFrac scale[2][2];
- Point p;
-
- SetPt(&p, fx >> 16, fy >> 16);
- if (!ModelessPtInRect(p, srcBounds))
- return false;
-
- if (p.h == srcBounds->right - 1)
- fx = ff(p.h);
- if (p.v == srcBounds->bottom - 1)
- fy = ff(p.v);
-
- /* Compute the addr of the first src pixel
- */
- {
- long* srcAddr = srcBaseAddr + p.v * srcRowLongs + p.h;
-
- srcPixel[0][0] = *srcAddr++;
- srcPixel[0][1] = *srcAddr++;
- srcAddr += srcRowLongs;
- srcPixel[1][1] = *--srcAddr;
- srcPixel[1][0] = *--srcAddr;
- }
-
- /* Precompute the scales for each pixel
- */
- { shortFrac xFrac = Fixed2ShortFrac((unsigned short)fx);
- shortFrac yFrac = Fixed2ShortFrac((unsigned short)fy);
-
- scale[0][0] = ShortFracMul(oneShortFrac - xFrac, oneShortFrac - yFrac);
- scale[0][1] = ShortFracMul(xFrac, oneShortFrac - yFrac);
- scale[1][0] = ShortFracMul(oneShortFrac - xFrac, yFrac);
- scale[1][1] = ShortFracMul(xFrac, yFrac);
- }
-
- /*
- * Now scale each component of each corner by the percentage coverage by the filter
- */
- tempBlue = ShortFracMulByte(scale[0][0], srcPixel[0][0]) +
- ShortFracMulByte(scale[0][1], srcPixel[0][1]) +
- ShortFracMulByte(scale[1][0], srcPixel[1][0]) +
- ShortFracMulByte(scale[1][1], srcPixel[1][1]);
- if (tempBlue == 256) tempBlue = 255;
- Assert(tempBlue >= 0 && tempBlue < 256);
-
- tempGreen = ShortFracMulByte(scale[0][0], srcPixel[0][0] >> 8) +
- ShortFracMulByte(scale[0][1], srcPixel[0][1] >> 8) +
- ShortFracMulByte(scale[1][0], srcPixel[1][0] >> 8) +
- ShortFracMulByte(scale[1][1], srcPixel[1][1] >> 8);
- if (tempGreen == 256) tempGreen = 255;
- Assert(tempGreen >= 0 && tempGreen < 256);
-
- tempRed = ShortFracMulByte(scale[0][0], srcPixel[0][0] >> 16) +
- ShortFracMulByte(scale[0][1], srcPixel[0][1] >> 16) +
- ShortFracMulByte(scale[1][0], srcPixel[1][0] >> 16) +
- ShortFracMulByte(scale[1][1], srcPixel[1][1] >> 16);
- if (tempRed == 256) tempRed = 255;
- Assert(tempRed >= 0 && tempRed < 256);
-
- *dstLong = (tempRed << 16) | (tempGreen << 8) | tempBlue;
- return true;
- }
-
- LockGWorldPixels(GWorldPtr world, Boolean lockIt)
- {
- if (lockIt)
- LockPixels(GetGWorldPixMap(world));
- else
- UnlockPixels(GetGWorldPixMap(world));
- }
-
- void SetGWorldPixel(GWorldPtr world, short x, short y)
- {
- GDHandle oldGD;
- GWorldPtr oldGW;
-
- GetGWorld(&oldGW,&oldGD);
- SetGWorld(world, nil);
- LockGWorldPixels(world, true);
- MoveTo(x, y);
- LineTo(x, y);
- LockGWorldPixels(world, false);
- SetGWorld(oldGW,oldGD);
- }
-
- void EraseGWorld( GWorldPtr world, Rect* bounds )
- {
- GDHandle oldGD;
- GWorldPtr oldGW;
-
- GetGWorld(&oldGW,&oldGD);
- SetGWorld(world, nil);
- LockGWorldPixels(world, true);
- EraseRect( bounds );
- LockGWorldPixels(world, false);
- SetGWorld(oldGW,oldGD);
- }
-
- void FancyMap(const Rect* srcRect, Fixed* xPtr, Fixed* yPtr)
- {
- double x = *xPtr / 65536.0;
- double dx = 2 * 3.1415926 * (x - (srcRect->right + srcRect->left >> 1)) / (srcRect->right - srcRect->left);
- double amp = srcRect->right - srcRect->left >> 3;
- double delta = sin(dx) * amp;
-
- *yPtr += delta * 65536.0;
- }
-
- void FancyMapBounds(Rect* bounds)
- {
- short width = bounds->right - bounds->left;
- short height = bounds->bottom - bounds->top;
-
- bounds->top -= width >> 3;
- bounds->bottom += width >> 3;
- }
-
- GWorldPtr MapGWorld(GWorldPtr srcWorld, mapping* dstMapping, GWorldPtr* maskWorld)
- {
- GWorldPtr dstWorld;
- PixMapHandle srcPixMap, dstPixMap;
- long *srcBaseAddr, *dstBaseAddr, srcRowLongs, dstRowLongs;
- Rect srcRect, dstRect;
- mapping inverseMapping;
- short x, y, mmuMode;
-
- /* Create the dstWorld sized to hold the transformed srcWorld
- */
- dstRect = srcRect = srcWorld->portRect;
- MapRectangle(dstMapping, &dstRect);
- if (NewGWorld(&dstWorld, 32, &dstRect, 0, 0, 0))
- return 0;
-
- /* Optionally, create a maskWorld with the same bounds as the dstWorld
- */
- if (maskWorld)
- { if (NewGWorld(maskWorld, 1, &dstRect, 0, 0, 0))
- { DisposeGWorld(dstWorld);
- return 0;
- }
- EraseGWorld(*maskWorld, &dstRect);
- }
-
- /* Setup for fast walking of the src and dst. Need to swap MMU mode to look at the baseAddr.
- */
- srcPixMap = GetGWorldPixMap( srcWorld );
- dstPixMap = GetGWorldPixMap( dstWorld );
- srcBaseAddr = (long *) GetPixBaseAddr ( srcPixMap ); /* get the address of the pixmap */
- srcRowLongs = ((**srcPixMap).rowBytes & 0x7fff) >> 2; /* get the row increment */
- dstBaseAddr = (long *) GetPixBaseAddr ( dstPixMap ); /* get the address of the pixmap */
- dstRowLongs = ((**dstPixMap).rowBytes & 0x7fff) >> 2; /* get the row increment */
-
- LockPixels(srcPixMap);
- LockPixels(dstPixMap);
-
- inverseMapping = *dstMapping;
- InvertMapping(&inverseMapping);
-
- mmuMode = true32b;
- SwapMMUMode(&mmuMode);
- for (y = dstRect.top; y < dstRect.bottom; y++)
- { long* dstAddr = dstBaseAddr;
-
- for (x = dstRect.left; x < dstRect.right; x++)
- { Fixed srcX = ff(x);
- Fixed srcY = ff(y);
-
- MapXY(&inverseMapping, &srcX, &srcY);
- if (GetFractionalPixel(srcBaseAddr, srcRowLongs, &srcRect, srcX, srcY, dstAddr++) && maskWorld)
- SetGWorldPixel(*maskWorld, x, y);
- }
- dstBaseAddr += dstRowLongs;
- }
- SwapMMUMode(&mmuMode);
-
- UnlockPixels(srcPixMap);
- UnlockPixels(dstPixMap);
-
- return dstWorld;
- }
-
- /* Editor's Note: I modified this routine to always use the tent filter, for demo purposes. There's a similar routine
- below that uses only the box filter, and the more general routine that's in the article is above */
- GWorldPtr MapGWorldTent(GWorldPtr srcWorld, mapping* dstMapping, GWorldPtr* maskWorld)
- {
- GWorldPtr dstWorld;
- PixMapHandle srcPixMap, dstPixMap;
- long *srcBaseAddr, *dstBaseAddr, srcRowLongs, dstRowLongs;
- Rect srcRect, dstRect;
- mapping inverseMapping;
- short x, y, mmuMode;
-
- /* Create the dstWorld sized to hold the transformed srcWorld
- */
- dstRect = srcRect = srcWorld->portRect;
- MapRectangle(dstMapping, &dstRect);
- if (NewGWorld(&dstWorld, 32, &dstRect, 0, 0, 0))
- return 0;
-
- /* Optionally, create a maskWorld with the same bounds as the dstWorld
- */
- if (maskWorld)
- { if (NewGWorld(maskWorld, 1, &dstRect, 0, 0, 0))
- { DisposeGWorld(dstWorld);
- return 0;
- }
- EraseGWorld(*maskWorld, &dstRect);
- }
-
- /* Setup for fast walking of the src and dst. Need to swap MMU mode to look at the baseAddr.
- */
- srcPixMap = GetGWorldPixMap( srcWorld );
- dstPixMap = GetGWorldPixMap( dstWorld );
- srcBaseAddr = (long *) GetPixBaseAddr ( srcPixMap ); /* get the address of the pixmap */
- srcRowLongs = ((**srcPixMap).rowBytes & 0x7fff) >> 2; /* get the row increment */
- dstBaseAddr = (long *) GetPixBaseAddr ( dstPixMap ); /* get the address of the pixmap */
- dstRowLongs = ((**dstPixMap).rowBytes & 0x7fff) >> 2; /* get the row increment */
-
- LockPixels(srcPixMap);
- LockPixels(dstPixMap);
-
- inverseMapping = *dstMapping;
- InvertMapping(&inverseMapping);
-
- mmuMode = true32b;
- SwapMMUMode(&mmuMode);
- for (y = dstRect.top; y < dstRect.bottom; y++)
- { long* dstAddr = dstBaseAddr;
-
- for (x = dstRect.left; x < dstRect.right; x++)
- { Fixed srcX = ff(x);
- Fixed srcY = ff(y);
-
- MapXY(&inverseMapping, &srcX, &srcY);
- if (GetFractionalPixelTent(srcBaseAddr, srcRowLongs, &srcRect, srcX, srcY, dstAddr++) && maskWorld)
- SetGWorldPixel(*maskWorld, x, y);
- }
- dstBaseAddr += dstRowLongs;
- }
- SwapMMUMode(&mmuMode);
-
- UnlockPixels(srcPixMap);
- UnlockPixels(dstPixMap);
-
- return dstWorld;
- }
-
- /* Editor's Note: I modified this routine to always use the box filter, for demo purposes. There's a similar routine
- above that uses only the tent filter */
- GWorldPtr MapGWorldBox(GWorldPtr srcWorld, mapping* dstMapping, GWorldPtr* maskWorld)
- {
- GWorldPtr dstWorld;
- PixMapHandle srcPixMap, dstPixMap;
- long *srcBaseAddr, *dstBaseAddr, srcRowLongs, dstRowLongs;
- Rect srcRect, dstRect;
- mapping inverseMapping;
- short x, y, mmuMode;
-
- /* Create the dstWorld sized to hold the transformed srcWorld
- */
- dstRect = srcRect = srcWorld->portRect;
- MapRectangle(dstMapping, &dstRect);
- if (NewGWorld(&dstWorld, 32, &dstRect, 0, 0, 0))
- return 0;
-
- /* Optionally, create a maskWorld with the same bounds as the dstWorld
- */
- if (maskWorld)
- { if (NewGWorld(maskWorld, 1, &dstRect, 0, 0, 0))
- { DisposeGWorld(dstWorld);
- return 0;
- }
- EraseGWorld(*maskWorld, &dstRect);
- }
-
- /* Setup for fast walking of the src and dst. Need to swap MMU mode to look at the baseAddr.
- */
- srcPixMap = GetGWorldPixMap( srcWorld );
- dstPixMap = GetGWorldPixMap( dstWorld );
- srcBaseAddr = (long *) GetPixBaseAddr ( srcPixMap ); /* get the address of the pixmap */
- srcRowLongs = ((**srcPixMap).rowBytes & 0x7fff) >> 2; /* get the row increment */
- dstBaseAddr = (long *) GetPixBaseAddr ( dstPixMap ); /* get the address of the pixmap */
- dstRowLongs = ((**dstPixMap).rowBytes & 0x7fff) >> 2; /* get the row increment */
-
- LockPixels(srcPixMap);
- LockPixels(dstPixMap);
-
- inverseMapping = *dstMapping;
- InvertMapping(&inverseMapping);
-
- mmuMode = true32b;
- SwapMMUMode(&mmuMode);
- for (y = dstRect.top; y < dstRect.bottom; y++)
- { long* dstAddr = dstBaseAddr;
-
- for (x = dstRect.left; x < dstRect.right; x++)
- { Fixed srcX = ff(x);
- Fixed srcY = ff(y);
-
- MapXY(&inverseMapping, &srcX, &srcY);
- if (GetFractionalPixelBox(srcBaseAddr, srcRowLongs, &srcRect, srcX, srcY, dstAddr++) && maskWorld)
- SetGWorldPixel(*maskWorld, x, y);
- }
- dstBaseAddr += dstRowLongs;
- }
- SwapMMUMode(&mmuMode);
-
- UnlockPixels(srcPixMap);
- UnlockPixels(dstPixMap);
-
- return dstWorld;
- }
-
- /* Editor's Note: I modified this routine to always use the fancy mapping (sine wave), for demo purposes. */
- GWorldPtr FancyMapGWorld(GWorldPtr srcWorld, mapping* dstMapping, GWorldPtr* maskWorld)
- {
- GWorldPtr dstWorld;
- PixMapHandle srcPixMap, dstPixMap;
- long *srcBaseAddr, *dstBaseAddr, srcRowLongs, dstRowLongs;
- Rect srcRect, dstRect;
- mapping inverseMapping;
- short x, y, mmuMode;
-
- /* Create the dstWorld sized to hold the transformed srcWorld
- */
- dstRect = srcRect = srcWorld->portRect;
- MapRectangle(dstMapping, &dstRect);
- FancyMapBounds(&dstRect);
- if (NewGWorld(&dstWorld, 32, &dstRect, 0, 0, 0))
- return 0;
-
- /* Optionally, create a maskWorld with the same bounds as the dstWorld
- */
- if (maskWorld)
- { if (NewGWorld(maskWorld, 1, &dstRect, 0, 0, 0))
- { DisposeGWorld(dstWorld);
- return 0;
- }
- EraseGWorld(*maskWorld, &dstRect);
- }
-
- /* Setup for fast walking of the src and dst. Need to swap MMU mode to look at the baseAddr.
- */
- srcPixMap = GetGWorldPixMap( srcWorld );
- dstPixMap = GetGWorldPixMap( dstWorld );
- srcBaseAddr = (long *) GetPixBaseAddr ( srcPixMap ); /* get the address of the pixmap */
- srcRowLongs = ((**srcPixMap).rowBytes & 0x7fff) >> 2; /* get the row increment */
- dstBaseAddr = (long *) GetPixBaseAddr ( dstPixMap ); /* get the address of the pixmap */
- dstRowLongs = ((**dstPixMap).rowBytes & 0x7fff) >> 2; /* get the row increment */
-
- LockPixels(srcPixMap);
- LockPixels(dstPixMap);
-
- inverseMapping = *dstMapping;
- InvertMapping(&inverseMapping);
-
- mmuMode = true32b;
- SwapMMUMode(&mmuMode);
- for (y = dstRect.top; y < dstRect.bottom; y++)
- { long* dstAddr = dstBaseAddr;
-
- for (x = dstRect.left; x < dstRect.right; x++)
- { Fixed srcX = ff(x);
- Fixed srcY = ff(y);
-
- MapXY(&inverseMapping, &srcX, &srcY);
- FancyMap(&srcRect, &srcX, &srcY);
- if (GetFractionalPixelBox(srcBaseAddr, srcRowLongs, &srcRect, srcX, srcY, dstAddr++) && maskWorld)
- SetGWorldPixel(*maskWorld, x, y);
- }
- dstBaseAddr += dstRowLongs;
- }
- SwapMMUMode(&mmuMode);
-
- UnlockPixels(srcPixMap);
- UnlockPixels(dstPixMap);
-
- return dstWorld;
- }
-
- GWorldPtr PictToGWorld( PicHandle pict, Rect* bounds )
- {
- GWorldPtr world;
- short err;
-
- *bounds = (*pict)->picFrame;
- OffsetRect(bounds, -bounds->left, -bounds->top);
-
- if (!(err = NewGWorld(&world, 32, bounds, 0, 0, 0)))
- { GDHandle oldGD;
- GWorldPtr oldGW;
-
- GetGWorld(&oldGW,&oldGD);
- SetGWorld(world,nil);
- EraseRect( bounds );
- DrawPicture( pict, bounds);
- SetGWorld(oldGW,oldGD);
-
- return world;
- }
- else
- return nil;
- }
-
- void CenterRect(Rect* r, short x, short y)
- {
- OffsetRect(r, x - (r->right + r->left >> 1), y - (r->bottom + r->top >> 1));
- }
-